/**
**************************************************************************************
*Founder Effect                                                                      *
*Copyright (C) 2006-2007, 5d Studios (www.5d-Studios.com)                            *
*                                                                                    *
*This library is free software; you can redistribute it and/or                       *
*modify it under the terms of the GNU Lesser General Public                          *
*License as published by the Free Software Foundation; either                        *
*version 2.1 of the License, or (at your option) any later version.                  *
*                                                                                    *
*This library is distributed in the hope that it will be useful,                     *
*but WITHOUT ANY WARRANTY; without even the implied warranty of                      *
*MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU                   *
*Lesser General Public License for more details.                                     *
*                                                                                    *
*You should have received a copy of the GNU Lesser General Public                    *
*License along with this library; if not, write to the Free Software                 *
*Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA      *
**************************************************************************************
*/
#include "StdAfx.h"
#include "MDialogBox.h"

#include "../shared/StringUtil.h"
#include "../Kernel.h"

extern Kernel* g_kernel;

/*-------------------------------------------------------------
    Define shortcuts
--------------------------------------------------------------*/
#define JOYSTICK_XAXIS ( g_kernel->GetInput()->GetJoystickX() )
#define JOYSTICK_YAXIS ( g_kernel->GetInput()->GetJoystickY() )

#define JOYSTICK_BUTTON( str ) ( g_kernel->GetInput()->IsJoystickButtonDown( g_kernel->GetCvars()->GetFloatValue( str ) ) )
#define KEY_BUTTON( str ) ( g_kernel->GetInput()->IsKeyDown( g_kernel->GetCvars()->GetFloatValue( str ) ) )

#define TIME (g_kernel->GetTime())



namespace gui
{

MDialogBox::MDialogBox(const gui::Component *c) : gui::Component(c)
{
}

MDialogBox::~MDialogBox(void) 
{
    gui::Component::~Component();
}

    /** Load a conversation from a file */
bool MDialogBox::LoadDialog( const std::string &file )
{
    return m_model.LoadDialog( file );
}

///** Update this component */
//void MDialogBox::Update( long dt )
//{
//    // now draw all sub components
//    gui::Component::Update( dt );
//}

void MDialogBox::Render( IRender* r )
{
    // draw a trim
    r->SetColor( 0 , 0 , 0 );
    r->DrawRect( m_pos.x, m_pos.y, m_width, m_height );

    /*-----------------------------------------------------
        Header 
    ------------------------------------------------------*/
    r->SetColor( 0.16f, 0.16f, 0.14f );
    r->FillRect( m_pos.x, m_pos.y, m_width, m_height - (m_height + 15) );
    r->SetColor( 0, 0, 0 );
    // always draw a header
    r->DrawRect( m_pos.x, m_pos.y, m_width, m_height - (m_height + 15) );
    r->SetColor( 1, 1, 1 );
    r->DrawString( m_pos.x, m_pos.y - 15, GetTitle().c_str() );

    /*-----------------------------------------------------
        Background
    ------------------------------------------------------*/
    r->SetColor( m_bColor.GetX(), m_bColor.GetY(), m_bColor.GetZ(), GetAlpha() );
    // r->SetColor( 0.2f, 0.5f, 0.7f, 0.6f );
    r->FillRect( m_pos.x, m_pos.y, m_width, m_height );    
    r->SetColor( 0 , 0 , 0 );
    r->DrawRect( m_pos.x, m_pos.y, m_width, m_height );

    /*-----------------------------------------------------
        Text 
    ------------------------------------------------------*/
    WrapText( m_model.GetText(), m_width, m_height );
    int y = 0, i = 0;
    type_Strings::iterator it;
    for( it = m_nextLine.begin() ; it != m_nextLine.end(); ++it, ++i )
    {
            y =  m_pos.y + ( i*r->GetTextHeight('H') );
            if ( y <= m_pos.y - 40 ) {             
                continue;
            }
			// Indicate that there is text above
            if ( y >= m_height - 40 ) {
                continue;
            }
           
            r->DrawString( m_pos.x ,  y, (*it).c_str()  );
    }
    /*-----------------------------------------------------
        Draw response options
    --------------------------------------------------------*/
    if ( !m_model.GetResponses() ) return;
    // draw the response options
    r->SetColor( 0 , 0 , 0 );
    r->FillRect( m_pos.x, m_pos.y + m_height - 30 , m_width, 2 );
    std::string str;
    int pos = 0;
    for ( int i = 1;i <= m_model.GetResponses()->size; ++i )
    {   str = m_model.GetResponses()->m_responsePossibilites[i-1].response;
        pos += (i-1)*13*str.length() + 15;
        r->DrawString( m_pos.x + pos, m_pos.y + m_height - 20, str.c_str() );
    }
    if ( !str.empty() )
    {
        r->SetColor( 0.25f, 0.15f, 0.15f );
        r->FillCircle( 5, m_pos.x + m_model.GetIndex()*13*str.length() + 8, m_pos.y + m_height - 12 );
    }

    // now draw all sub components
    gui::Component::Render( r );
}

/** Wrap text to fit in a desired location */
void MDialogBox::WrapText(const std::string &text, int width, int height )
{
    StringUtil util( text, ' ' );
    type_Strings lines;
    m_nextLine.clear();
    while ( util.HasNext() )
    {
        lines.push_back( util.GetNext() );
    }

    std::string currentLine, currentTemp;
    while ( !lines.empty() )
    {
        currentTemp = lines.front();
        // TODO get the proper width of chars
        if ( (currentTemp.size() + currentLine.size()) * 10 < width )
        {
            currentLine += " " + currentTemp;
            lines.pop_front();
        }
        else
        {
            m_nextLine.push_back( currentLine );
            currentLine.clear();
        }
    }
    m_nextLine.push_back( currentLine );
        
    
}

/** Handle the input */
bool MDialogBox::HandleInput()
{
    if ( HasFocus() )
    {
        if ( !m_model.GetNumberOfResponses() ) {
            
            // User presses "Enter" to exit dialog state
            if ( JOYSTICK_BUTTON( "+j_attack1" ) || KEY_BUTTON( "+attack1") )
            {
                if ( g_kernel->GetGame()->GetCurrentState()->GetName() == "DialogState" )
                {
                    g_kernel->GetGame()->PopState();
                    SetVisible( false );
                    SetFocus( false );
                }
            }
     
        }
        else {
            // get the number of options
            int size = m_model.GetResponses()->size;

            // Move the Index value
            if ( KEY_BUTTON( "+right" ) || JOYSTICK_XAXIS > 20000 )
            {
                m_model.SelectNextResponse();
            } 
            else if ( KEY_BUTTON( "+left" ) || JOYSTICK_XAXIS < -20000 )
            {
                m_model.SelectPrevResponse();
            }

            // User presses "Enter"
            if ( JOYSTICK_BUTTON( "+j_attack1" ) || KEY_BUTTON( "+attack1") )
            {
                // TODO - Put this stuff in a script
                int response = m_model.GetIndex();
                std::string str = m_model.GetResponses()->m_responsePossibilites[ response ].response;
                std::string mission = m_model.GetResponses()->m_responsePossibilites[ response ].mission_name;
                m_model.Respond( str );

                if ( mission != "null" )
                {
                    IEvent evt( EVT_DIALOG, TIME, new DialogEvent(response, mission, 1), LT_MISSION_DISPATCHER );
                    // fire a response event
                    EventManager::GetInstance()->TriggerEvent( evt );
                }
            }
        }
        return true;
    }
    // now handle input on all sub components
    return gui::Component::HandleInput();

}

};